#ifndef CLIENT_HPP
#define CLIENT_HPP

#include <QWidget>
#include <QObject>
#include <QByteArray>
#include <QDataStream>
#include <QTcpSocket>
#include <QMessageBox>
#include <QStringList>

#include "mainwindow.hpp"
#include "../../src/idmanager.hpp"
#include "game.hpp"

class MainWindow;

class Client : public QObject
{

private:
    Q_OBJECT

    MainWindow * _mainWindow;

    QTcpSocket * _socket;
    QByteArray * _paquet;
    QDataStream * _in;
    QDataStream * _out;
    quint16 _messageSize;

    bool _connected;

private:
    void prePaquet();
    void postPaquet();
    void writeStamp(Mid::MessageID mid);
    void dispatch(Mid::MessageID mid);

public:
    Client(MainWindow * mainWindow);
    ~Client();

    const QTcpSocket * socket();

private slots:
    //! Appelée dès qu'on reçoit des données par la socket
    void donneesRecues();
    void deconnexion();

signals:
    void NTconnected();
    void NTinscriptionFailed();
    void NTinscriptionSuccessful();
    void NTconnectionFailed(quint8 failReason);
    void NTmotd(const QString & message);
    void NTlobbySaid(const QString & message);
    void NTclientConnected(const QString & message);
    void NTclientDisconnected(const QString & message);
    void NTclientList(const QStringList & liste);
    void NTgameCreated(quint8 idPartie, quint8 gobanSize, qreal komi, const QString & black);
    void NTheSees(quint8 idPartie, const QString & name);
    void NTheDoesntSeeAnymore(quint8 idPartie, const QString & name);
    void NTgameStarts(quint8 idPartie, const QString & whiteName);
    void NTgameLeft(quint8 idPartie, quint8 playerID); // 0 : black, 1 : white
    void NTgameDestroyed(quint8 idPartie);
    void NTillegalMessage(const QString & message);
    void NTgameList(const QList<Game *> & gameList);
    void NTnotExists(quint8 idPartie);
    void NTgameSaid(quint8 idPartie, const QString & message);
    void NTgameState(quint8 idPartie, const QStringList & observerList, const QVector < QVector<quint8> > & map);
    void NTobserverList(quint8 idPartie, const QStringList & observerList);
    void NTmovePlayed(quint8 idPartie, quint8 playerID, quint8 x, quint8 y);
    void NTbadMove(quint8 idPartie);
    void NTnewScore(quint8 idPartie, quint8 playerID, qreal newScore);
    void NTturnSkipped(quint8 idPartie, quint8 playerID);
    void NTmovesFinished(quint8 idPartie);
    void NTgroupKilled(quint8 idPartie, quint8 x, quint8 y);
    void NTgroupSaved(quint8 idPartie, quint8 x, quint8 y);
    void NTtoPlayAgain(quint8 idPartie);
    void NTgroupsValidated(quint8 idPartie, quint8 playerID);
    void NTgameover(quint8 idPartie, qreal blackScore, qreal whiteScore);

    void disconnected();
    void connectionReussie();
    void connectionRatee();
    void inscription();

public slots:
    void reactInscriptionFailed();
    void reactConnectionFailed(quint8 failReason);
    void reactConnected();
    void reactInscriptionSuccessful();
    void reactIllegalMessage(const QString & message);
    void reactNotExists(quint8 idPartie);
    void connecter(const QString & ip, quint16 port);

    void send(Mid::MessageID mid, const QString & s0);
    void send(Mid::MessageID mid, const QString & s0, const QString & s1);
    void send(Mid::MessageID mid, quint8 i0);
    void send(Mid::MessageID mid, quint8 i0, const QString & s0);
    void send(Mid::MessageID mid, quint8 i0, qreal r0);
    void send(Mid::MessageID mid);
    void send(Mid::MessageID mid, quint8 i0, quint8 x, quint8 y);
};

#endif // CLIENT_HPP
